/*
 * variadic_printf.cpp
 *
 * Demonstrating how to output variadic arguments as specified by the
 * format string.
 *
 */

#include <cstdarg>
#include <cstdio>
#include <fstream>



std::ofstream stream("variadic.output");



static void A(const char* fmt, ...)
{
    std::va_list args;
    va_start(args, fmt);

    std::vfprintf(stdout, fmt, args);
    // or
    // std::vprintf(fmt, args);

    va_end(args);
}



template <class... Types>
static void B(const char* fmt, const Types&... args)
{
    std::fprintf(stdout, fmt, args...);
    // or
    // std::printf(fmt, args...);
}



static void C(const char* fmt, ...)
{
    std::va_list args, copied;
    va_start(args, fmt);

    va_copy(copied, args);
    char* buffer = new char[std::vsnprintf(nullptr, 0, fmt, copied) + 1]; // +1 for '\0'
    std::vsprintf(buffer, fmt, args);
    stream << buffer;

    delete[] buffer;
    va_end(copied);
    va_end(args);
}



template <class... Types>
static void D(const char* fmt, const Types&... args)
{
    char* buffer = new char[std::snprintf(nullptr, 0, fmt, args...) + 1]; // +1 for '\0'

    std::sprintf(buffer, fmt, args...);
    stream << buffer;

    delete[] buffer;
}



int main()
{
    A("\n%s won the %2dth FIFA World Cup!\n", "Argentina", 22);

    B("\n%s uses %13s to shoot the %d eagles.\n", "Bower", "Hoyt Highline", 2);

    C("\n%s is easy as pie!\n", "Cxx");

    D("\n%s counted the money again. %4.2f dollars. That was all.\n\n", "Della", 1.87);

    std::printf("\n");
    return 0;
}

